from flask import Blueprint, request, jsonify
from flask_jwt_extended import jwt_required
from app import db
from app.models import Menu
from app.utils.decorators import admin_required

menus_bp = Blueprint('menus', __name__)

@menus_bp.route('/', methods=['GET'])
@jwt_required()
@admin_required
def get_menus():
    """获取菜单列表（树形结构）"""
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 100, type=int)
    search = request.args.get('search', '')
    
    # 只查询顶级菜单（parent_id 为 NULL）
    query = Menu.query.filter(Menu.parent_id.is_(None))
    
    if search:
        query = query.filter(
            db.or_(
                Menu.name.contains(search),
                Menu.code.contains(search),
                Menu.title.contains(search)
            )
        )
    
    # 按排序字段排序
    query = query.order_by(Menu.sort_order.asc(), Menu.id.asc())
    
    pagination = query.paginate(
        page=page, per_page=per_page, error_out=False
    )
    
    menus = pagination.items
    
    # 转换为树形结构
    tree_menus = []
    for menu in menus:
        tree_menu = menu.to_tree_dict()
        if tree_menu:
            tree_menus.append(tree_menu)
    
    return jsonify({
        'menus': tree_menus,
        'pagination': {
            'page': page,
            'per_page': per_page,
            'total': pagination.total,
            'pages': pagination.pages
        }
    }), 200

@menus_bp.route('/<int:menu_id>', methods=['GET'])
@jwt_required()
@admin_required
def get_menu(menu_id):
    """获取单个菜单详情"""
    menu = Menu.query.get(menu_id)
    
    if not menu:
        return jsonify({'message': '菜单不存在'}), 404
    
    return jsonify({'menu': menu.to_dict()}), 200

@menus_bp.route('/', methods=['POST'])
@jwt_required()
@admin_required
def create_menu():
    """创建菜单"""
    data = request.get_json()
    
    if not data:
        return jsonify({'message': '请求数据不能为空'}), 400
    
    # 检查必填字段
    required_fields = ['name', 'code']
    for field in required_fields:
        if not data.get(field):
            return jsonify({'message': f'字段 {field} 不能为空'}), 400
    
    # 检查code唯一性
    existing = Menu.query.filter_by(code=data['code']).first()
    if existing:
        return jsonify({'message': '菜单代码已存在'}), 400
    
    menu = Menu(
        name=data['name'],
        code=data['code'],
        parent_id=data.get('parent_id'),
        path=data.get('path'),
        component=data.get('component'),
        redirect=data.get('redirect'),
        icon=data.get('icon'),
        title=data.get('title'),
        hidden=data.get('hidden', False),
        sort_order=data.get('sort_order', 0),
        is_active=data.get('is_active', True)
    )
    
    try:
        db.session.add(menu)
        db.session.commit()
        return jsonify({
            'message': '菜单创建成功',
            'menu': menu.to_dict()
        }), 201
    except Exception as e:
        db.session.rollback()
        return jsonify({'message': f'菜单创建失败: {str(e)}'}), 500

@menus_bp.route('/<int:menu_id>', methods=['PUT'])
@jwt_required()
@admin_required
def update_menu(menu_id):
    """更新菜单"""
    menu = Menu.query.get(menu_id)
    
    if not menu:
        return jsonify({'message': '菜单不存在'}), 404
    
    data = request.get_json()
    
    if not data:
        return jsonify({'message': '请求数据不能为空'}), 400
    
    # 允许更新的字段
    allowed_fields = [
        'name', 'parent_id', 'path', 'component', 'redirect', 
        'icon', 'title', 'hidden', 'sort_order', 'is_active'
    ]
    
    for field in allowed_fields:
        if field in data:
            setattr(menu, field, data[field])
    
    try:
        db.session.commit()
        return jsonify({
            'message': '菜单更新成功',
            'menu': menu.to_dict()
        }), 200
    except Exception as e:
        db.session.rollback()
        return jsonify({'message': f'菜单更新失败: {str(e)}'}), 500

@menus_bp.route('/<int:menu_id>', methods=['DELETE'])
@jwt_required()
@admin_required
def delete_menu(menu_id):
    """删除菜单"""
    menu = Menu.query.get(menu_id)
    
    if not menu:
        return jsonify({'message': '菜单不存在'}), 404
    
    # 检查是否有子菜单
    if menu.children:
        return jsonify({'message': '请先删除子菜单'}), 400
    
    try:
        db.session.delete(menu)
        db.session.commit()
        return jsonify({'message': '菜单删除成功'}), 200
    except Exception as e:
        db.session.rollback()
        return jsonify({'message': f'菜单删除失败: {str(e)}'}), 500 